/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dp1.titandevelop.titano.service;

import dp1.titandevelop.titano.bean.Estado;
import dp1.titandevelop.titano.bean.ProduccionAux;
import dp1.titandevelop.titano.bean.ProductoAux;
import dp1.titandevelop.titano.persistent.Almacen;
import dp1.titandevelop.titano.persistent.AlmacenXProducto;
import dp1.titandevelop.titano.persistent.Asignacion;
import dp1.titandevelop.titano.persistent.OrdenProduccion;
import dp1.titandevelop.titano.persistent.Produccion;
import dp1.titandevelop.titano.persistent.PadreProduccion;
import dp1.titandevelop.titano.persistent.Permiso;
import dp1.titandevelop.titano.persistent.Producto;
import dp1.titandevelop.titano.persistent.Receta;
import java.sql.Array;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.cayenne.DataObjectUtils;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.access.DataContext;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.query.SelectQuery;
import dp1.titandevelop.titano.service.KardexService;
import dp1.titandevelop.titano.service.TipoMovimientoService;
import dp1.titandevelop.titano.service.EmpleadoXProcesoTurnoService;
import dp1.titandevelop.titano.view.LoginT;
import org.apache.cayenne.query.SQLTemplate;
import org.jdesktop.swingx.JXDatePicker;
/**
 *
 * @author dorita 
 */
public class ProduccionService {
    AsignacionService sa= new AsignacionService();
    KardexService sk= new KardexService();
    AlmacenService sl = new AlmacenService();
    EmpleadoXProcesoTurnoService se = new EmpleadoXProcesoTurnoService();
    
    TipoMovimientoService sm = new TipoMovimientoService();
    
    //Insertar un nuevo padre produccion junto a su detalle de produccion, realizar el llamado a movimiento de almacen    
    public void Insertar(Date d,ArrayList<Produccion> l, String des){
    //public void Insertar(Date d,ArrayList<Produccion> l) {
        ObjectContext c = DataContext.createDataContext();
        PadreProduccion p = c.newObject(PadreProduccion.class);
        p.setFecha(d);
        p.setDescripcion(des);
        c.commitChanges();  
        int j;
        ArrayList<ProductoAux> listaMov= new ArrayList<ProductoAux>();
        ArrayList<PadreProduccion> lp=this.BuscaPorFecha(d);
        PadreProduccion pp=lp.get(lp.size()-1);
        for (int i=0; i<l.size();i++)
        {
            this.InsertarDetalle(c,pp,l.get(i), listaMov);
        }
        //llamar a movimiento de almacen
          int idTMov1 = sm.buscarFiltrado("Salida Interna").get(0).getIdtipomovimiento();
        int idEmp= LoginT.empleadoLogin.getIdempleado();
        for (int i=0;i<listaMov.size();i++)
        {
           //otro metodo insertarConDoc(int idAlm, int idProd, int idTMov, int idEmp, Date in, Date fin,int cantidad, int doc) {
            sk.insertarConDoc(listaMov.get(i).alm.getIdalmacen(), listaMov.get(i).prod.getIdproducto(), idTMov1, idEmp, pp.getFecha(), pp.getFecha(),listaMov.get(i).cantidad, pp.getIdpadreproduccion());
          
        }
        //Calcular la cantidad producida por producto
        int idTMov = sm.buscarFiltrado("Entrada Interna").get(0).getIdtipomovimiento();
        ArrayList<ProduccionAux> lpa=buscaProductos(pp.getIdpadreproduccion(),c);
        for (int i=0;i<lpa.size();i++)
        {
           j=sl.movimientoAlmacen(pp.getIdpadreproduccion(), lpa.get(i).getIdProducto(), idTMov, (int)lpa.get(i).getProductividad());
           
        }
        
        Almacen alm = this.sl.obtenerTemporalPorProceso("Empaquetado");
        OrdenProduccionService so = new OrdenProduccionService();
        OrdenProduccion op=so.buscarEnProceso();
        if(sk.buscarPorDocAlm(op.getIdordenproduccion(),idTMov, alm.getIdalmacen()))
        {
            int stock=0;
            List<AlmacenXProducto> listAlm=alm.getAlmacenXProductoArray();
            for (int i=0; i<listAlm.size(); i++)
            {
                if(listAlm.get(i).getStock()!=0)
                {
                    stock+=listAlm.get(i).getStock();
                    break;
                }

            }

            if (stock==0) so.cambioEstadoDetalleOP_Cumplido(op.getIdordenproduccion());
        }
    }
    
   
    
    public void InsertarDetalle(ObjectContext c, PadreProduccion pp, Produccion p, ArrayList<ProductoAux> listaMov){
        Asignacion a=sa.BuscaPorId(c,p.getToAsignacion().getIdasignacion());
        ProductoXProcesoService spp= new ProductoXProcesoService();
        
        RecetaService sr = new RecetaService();
        Producto prod1= spp.DevueveSalida(a.getToProducto().getIdproducto(), a.getToMaquina().getToProceso().getIdproceso());
        
        ArrayList<Receta> rr = sr.BuscarPorProducto(prod1);
        for (int i =0; i<rr.size(); i++)
        {
            int idMaterial = rr.get(i).getToProducto1().getIdproducto();
            int cantidad = Math.round(rr.get(i).getCantidad()*(p.getProductividad()+p.getRotura()));
           // Almacen alm= buscaAlmacenTemporal(idMaterial, prod1.getToProceso().getIdproceso());
            AlmacenXProducto alm=sl.obtenerTemporalPorProd(idMaterial);
            
           //--se realiza automaticamente al realizar el movimiento: sk.actualizaEstadoAlmacen(c, alm.getToAlmacen().getIdalmacen(), idMaterial, "Salida Interna", cantidad);
            //Inserta movimiento de salida
            int indice =-1;
           
               for (int j=0 ; j<listaMov.size(); j++)
                {
                    int idProd = listaMov.get(j).prod.getIdproducto();
                    int idProc1 = prod1.getToProceso().getIdproceso();
                    int idProc2 = listaMov.get(j).proc.getIdproceso();
                    // si exioste ese insumo en ese proceso
                    if (idMaterial == idProd && idProc1 == idProc2)
                    {
                        indice=j;
                        break;
                    }
                }
             if (indice==-1){
                        ProductoAux pa= new ProductoAux();
                        pa.alm= alm.getToAlmacen();
                        pa.cantidad= cantidad;
                        pa.proc= prod1.getToProceso();
                        pa.prod= rr.get(i).getToProducto1();
                        listaMov.add(pa);
                     
                    }
             else {
                 listaMov.get(indice).cantidad=(listaMov.get(indice).cantidad+cantidad);
                }
            
        }
        PadreProduccion pp1=this.buscaPadrePorId(pp.getIdpadreproduccion(),c);
        Estado e= new Estado();
        Produccion p1 = c.newObject(Produccion.class);
        p1.setBeneficio(p.getBeneficio());
        p1.setCosto(p.getCosto());
        p1.setEstado(e.getActivo());
        p1.setProductividad(p.getProductividad());
        p1.setRotura(p.getRotura());
        p1.setToAsignacion(a);
        p1.setToPadreProduccion(pp1);
        c.commitChanges();
    }
    
    //public void ActualizarDetalle(ArrayList<Produccion> lp, PadreProduccion pp)
            public void ActualizarDetalle(ArrayList<Produccion> lp){
        ObjectContext c=DataContext.createDataContext();
        //PadreProduccion pp1= this.buscaPadrePorId(pp.getIdpadreproduccion());
        //pp1.setDescripcion(d);
        for (int i=0; i<lp.size();i++)
        {
            Produccion p1 = this.buscarDetallePorId(lp.get(i).getIdproduccion(),c);
            p1.setBeneficio(lp.get(i).getBeneficio());
            p1.setCosto(lp.get(i).getCosto());       
            p1.setProductividad(lp.get(i).getProductividad());
            p1.setRotura(lp.get(i).getRotura());
        }
                     
        c.commitChanges();
    }
    
     public ArrayList<PadreProduccion> BuscaPorFecha(Date d){
        ObjectContext c = DataContext.createDataContext();
        Expression q = ExpressionFactory.matchExp(PadreProduccion.FECHA_PROPERTY, d);
        SelectQuery s = new SelectQuery(PadreProduccion.class,q);       
        ArrayList<PadreProduccion> lp = (ArrayList<PadreProduccion>)c.performQuery(s);
        return lp;        
    }
    
    public PadreProduccion BuscaPorFecha(Date d, ObjectContext c){
        Expression q = ExpressionFactory.matchExp(PadreProduccion.FECHA_PROPERTY, d);
        SelectQuery s = new SelectQuery(PadreProduccion.class,q);       
        return (PadreProduccion) DataObjectUtils.objectForQuery(c, s);        
    }
    
    public ArrayList<PadreProduccion> BuscaPorRangos(Date dmin, Date dmax){
        ObjectContext c = DataContext.createDataContext();
        Expression q = ExpressionFactory.betweenExp(PadreProduccion.FECHA_PROPERTY, dmin, dmax);
        SelectQuery s = new SelectQuery(PadreProduccion.class,q);       
        ArrayList<PadreProduccion> lp = (ArrayList<PadreProduccion>)c.performQuery(s);
        return lp;           
    }
    
    public ArrayList<PadreProduccion> BuscarTodos(){
        ObjectContext c = DataContext.createDataContext();
        String cadena = "SELECT * FROM PADRE_PRODUCCION ORDER BY FECHA";
        SQLTemplate q = new SQLTemplate(PadreProduccion.class,cadena);
        ArrayList<PadreProduccion> lp = (ArrayList<PadreProduccion>)c.performQuery(q);
        return lp;        
    }
    
     public ArrayList<Produccion> SacaDetalle(int idProd){
        ObjectContext c=DataContext.createDataContext();
        ArrayList<Produccion> l = new ArrayList<Produccion>();
        PadreProduccion p = buscaPadrePorId(idProd, c);        
        for (int i=0;i<p.getProduccionArray().size();i++)
        {
            l.add(p.getProduccionArray().get(i));
        }
        return l;
    }
    
    
    public ArrayList<Produccion> SacaDetalle(int idProd, ObjectContext c){
        ArrayList<Produccion> l = new ArrayList<Produccion>();
        PadreProduccion p = buscaPadrePorId(idProd, c);        
        for (int i=0;i<p.getProduccionArray().size();i++)
        {
            l.add(p.getProduccionArray().get(i));
        }
        return l;
    }

    public PadreProduccion buscaPadrePorId(int idProd) {
        ObjectContext c = DataContext.createDataContext();
        Expression q = ExpressionFactory.matchExp(PadreProduccion.IDPADREPRODUCCION_PK_COLUMN, idProd);
        SelectQuery s = new SelectQuery(PadreProduccion.class,q);       
        return (PadreProduccion) DataObjectUtils.objectForQuery(c, s);    
    }
    
     public PadreProduccion buscaPadrePorId(int idProd, ObjectContext c) {       
        Expression q = ExpressionFactory.matchExp(PadreProduccion.IDPADREPRODUCCION_PK_COLUMN, idProd);
        SelectQuery s = new SelectQuery(PadreProduccion.class,q);       
        return (PadreProduccion) DataObjectUtils.objectForQuery(c, s);    
    }

    public Produccion buscarDetallePorId(Integer idProd) {
        ObjectContext c = DataContext.createDataContext();
        Expression q = ExpressionFactory.matchExp(Produccion.IDPRODUCCION_PK_COLUMN, idProd);
        SelectQuery s = new SelectQuery(Produccion.class,q);       
        return (Produccion) DataObjectUtils.objectForQuery(c, s);   
    }
    
    public Produccion buscarDetallePorId(Integer idProd, ObjectContext c) {
        Expression q = ExpressionFactory.matchExp(Produccion.IDPRODUCCION_PK_COLUMN, idProd);
        SelectQuery s = new SelectQuery(Produccion.class,q);       
        return (Produccion) DataObjectUtils.objectForQuery(c, s);   
    }

    public ArrayList<ProduccionAux> buscaProductos(int idProd, ObjectContext c) 
    {       
       ArrayList<ProduccionAux> lp = new ArrayList<ProduccionAux>();
       ArrayList<Produccion> lProd=this.SacaDetalle(idProd,c);
       float beneficio, merma, productividad, costo;
       for (int i=0;i<lProd.size();i++)
       {
           ProductoXProcesoService spp= new ProductoXProcesoService();
           Producto prod1= spp.DevueveSalida(lProd.get(i).getToAsignacion().getToProducto().getIdproducto(), lProd.get(i).getToAsignacion().getToMaquina().getToProceso().getIdproceso());
           //falta ver la receta porque la asignacion solo asigna a productos finales.
           int j=enLista(lp, prod1);//Devuelve la posicion del elemento en la lista, si no esta devuelve -1;
           if(j!= -1)
           {
               beneficio=lp.get(j).getBeneficio();
               beneficio+=lProd.get(i).getBeneficio();
               merma=lp.get(j).getMerma();
               merma+=lProd.get(i).getRotura();
               productividad=lp.get(j).getProductividad();
               productividad+=lProd.get(i).getProductividad();
               costo=lp.get(j).getCosto();
               costo+=lProd.get(i).getCosto();
               lp.get(j).setBeneficio(beneficio);
               lp.get(j).setCosto(costo);
               lp.get(j).setMerma(merma);
               lp.get(j).setProductividad(productividad);
           }
           else
           {
               ProduccionAux pa= new ProduccionAux();
               pa.setIdProducto(prod1.getIdproducto());
               pa.setProducto(prod1.getDescripcion());
               pa.setBeneficio(lProd.get(i).getBeneficio());
               pa.setCosto(lProd.get(i).getCosto());
               pa.setMerma(lProd.get(i).getRotura());
               pa.setProductividad(lProd.get(i).getProductividad());
               lp.add(pa);               
           }
       }
       return lp;        
    }
    
    public ArrayList<ProduccionAux> buscaProductos(int idProd) 
    {
       
       ArrayList<ProduccionAux> lp = new ArrayList<ProduccionAux>();
       ArrayList<Produccion> lProd=this.SacaDetalle(idProd);
       float beneficio, merma, productividad, costo;
       for (int i=0;i<lProd.size();i++)
       {
            ProductoXProcesoService spp= new ProductoXProcesoService();
           Producto prod1= spp.DevueveSalida(lProd.get(i).getToAsignacion().getToProducto().getIdproducto(), lProd.get(i).getToAsignacion().getToMaquina().getToProceso().getIdproceso());
           int j=enLista(lp, prod1);//Devuelve la posicion del elemento en la lista, si no esta devuelve -1;
           if(j!= -1)
           {
               beneficio=lp.get(j).getBeneficio();
               beneficio+=lProd.get(i).getBeneficio();
               merma=lp.get(j).getMerma();
               merma+=lProd.get(i).getRotura();
               productividad=lp.get(j).getProductividad();
               productividad+=lProd.get(i).getProductividad();
               costo=lp.get(j).getCosto();
               costo+=lProd.get(i).getCosto();
               lp.get(j).setBeneficio(beneficio);
               lp.get(j).setCosto(costo);
               lp.get(j).setMerma(merma);
               lp.get(j).setProductividad(productividad);
           }
           else
           {
               ProduccionAux pa= new ProduccionAux();
               pa.setIdProducto(prod1.getIdproducto());
               pa.setProducto(prod1.getDescripcion());
               pa.setBeneficio(lProd.get(i).getBeneficio());
               pa.setCosto(lProd.get(i).getCosto());
               pa.setMerma(lProd.get(i).getRotura());
               pa.setProductividad(lProd.get(i).getProductividad());
               lp.add(pa);               
           }
       }
       return lp;        
    }

    public int enLista(ArrayList<ProduccionAux> lp, Producto p) 
    {
        for (int j=0;j<lp.size();j++)
        {
            if (lp.get(j).getIdProducto()==p.getIdproducto()) return j;
        }
        return -1;
    }

    public ArrayList<Produccion> buscarProduccionPorFecha(Date fecha) {
       ArrayList<PadreProduccion> listaPProd = this.BuscaPorFecha(fecha);
       ArrayList<Produccion> listaProd= new ArrayList<Produccion>();
       for (int i=0; i<listaPProd.size(); i++)
       {
           listaProd.addAll(this.SacaDetalle(listaPProd.get(i).getIdpadreproduccion()));
       } 
       return listaProd;
        
        //To change body of generated methods, choose Tools | Templates.
    }
}
 